﻿using System.Collections;
using System.Collections.Generic;
using System.CodeDom;
using System;
using OrganizationName.CodeGeneration;
using OrganizationName.Common;

namespace OrganizationName.Factory
{
    public class Element : CollectionMaterial
    {
        public virtual Key Key { get; set; }

        public override void FinalizationPhase(ICodeContext codeContext)
        {
            if (Key != null)
            {
                Key.GenerateCode(codeContext.CreateChild(Key));
            }

            base.FinalizationPhase(codeContext);

            ICodeProvider parentCollection = codeContext.ParentContext.CodeProvider;

            if (IsParentCollectionArray(codeContext))
            {
                int indexOfThisElement = Utility.GetIndexOfElementInArray((codeContext.ParentContext.CodeProvider as AnonymousInstance).Element, this);
                codeContext.Statements.Add
                (
                    new CodeAssignStatement
                    (
                        new CodeArrayIndexerExpression
                        (
                            new CodeVariableReferenceExpression(parentCollection.UniqueId),
                            new CodeSnippetExpression(indexOfThisElement.ToString())
                        ),
                        ToRightHandSideExpression(codeContext)
                    )
                );
            }
            else if (IsParentCollectionDictionary(codeContext))
            {
                if (Key == null)
                {
                    throw new CodeGenerationException("The Key element is required because the collection is an implementation of IDictionary or a supported key/value collection.", codeContext, null);
                }
                codeContext.Statements.Add
                (
                    new CodeMethodInvokeExpression
                    (
                        new CodeVariableReferenceExpression(parentCollection.UniqueId),
                        "Add",
                        Key.ToRightHandSideExpression(codeContext.CreateChild(Key)),
                        ToRightHandSideExpression(codeContext)
                    )
                );
            }
            else if (IsParentCollectionList(codeContext))
            {
                codeContext.Statements.Add
                (
                    new CodeMethodInvokeExpression
                    (
                        new CodeVariableReferenceExpression(parentCollection.UniqueId),
                        "Add",
                        ToRightHandSideExpression(codeContext)
                    )
                );
            }
            else
            {
                throw new CodeGenerationException("The parent of the Element is not a collection or is not a supported collection.", codeContext, null);
            }
        }

        protected override System.Type GetCollectionType(ICodeContext codeContext)
        {
            return (codeContext.ParentContext.CodeProvider as GenericMaterial).GetConcreteType(codeContext.ParentContext);
        }

        public override System.Type GetConcreteType(ICodeContext codeContext)
        {
            if (!string.IsNullOrEmpty(Impl))
            {
                return base.GetConcreteType(codeContext);
            }
            else
            {
                return base.GetCollectionValueType(codeContext);
            }
        }
    }
}
